module Project1(SW,KEY,LEDR,LEDG,HEX0,HEX1,HEX2,HEX3,CLOCK_50);
	input  [9:0] SW;
	input  [3:0] KEY;
	input  CLOCK_50;
	output [9:0] LEDR;
	output [7:0] LEDG;
	output [6:0] HEX0,HEX1,HEX2,HEX3;
	// Project1 uses the existing 50MHz clock (no need for a PLL)
	wire clk=CLOCK_50;
	// No need to use reset/locked because CLOCK_50 is always OK
	
	// Clock set on or off (should be initially off, but here it's on to see blinking)
	reg ClockSet = 1'b0;
	reg [6:0] ClockSetCounter = 7'b0;

	// Timing signals for centiseconds (100th of a second), semiseconds (1/2 of a second),
	//	seconds, decaseconds (10 seconds), minutes, decaminutes (10 minutes), and hours,
	// decahours (10 hours), and days
	
	wire [5:0] clocksec;
	wire [3:0] clocksecones, clockdecasec; //clock doesn't use these
	wire [3:0] clockmin, clockdecamin, clockhour;
	wire [1:0] clockdecahour;
	Timer clock(CLOCK_50, addmin, addhour, clocksec, clocksecones, clockdecasec, clockmin, clockdecamin, clockhour, clockdecahour, 0);
	reg sigcentisec = 1'b0;
	reg sigsemisec = 1'b0;
	reg [18:0] cntcentisec=19'd0;
	reg [5:0] cntsemisec = 6'd0;
	reg [11:0] Key1Counter = 12'b0;
	reg HourSet=1'b0;
	reg addhour = 1'b0;
	reg addmin = 1'b0;
	reg DontSetHours = 0;
	reg ClockSetDummy = 0;
	always @(posedge clk) begin
		sigcentisec <= 0;
		sigsemisec <= 0;
		if(cntcentisec!=19'd499999)
			cntcentisec<=cntcentisec+19'b1;
		else begin
			cntcentisec<=19'd0;
			sigcentisec<=1'b1;
			if(cntsemisec != 49)
				cntsemisec <= cntsemisec + 1;
			else begin
				cntsemisec <= 0;
				sigsemisec <= 1;
			end
		end

		// clock set incrementing
		if (ClockSet) begin
			// track how long the button has been held
			if (sigcentisec && !KEY[1] && !DontSetHours)
				Key1Counter <= Key1Counter + 12'b1;
			
			// hour incrementing
			if (Key1Counter == 12'd99) begin
				addhour <= 1'b1;
				// go into hour set mode so that we don't add a minute on release
				HourSet<=1'b1;
				Key1Counter<=12'd0;
			end
			else
				addhour <= 1'b0;
			
			// minute incrementing
			if (KEY[1]) begin
				DontSetHours <= 0;
				Key1Counter<=12'b0;
				// come out of hour set mode on next cycle
				HourSet<=1'b0;
				// if the button was pressed for less than a second
				if ((Key1Counter > 12'b0) && (Key1Counter < 12'd99) && !HourSet) begin
					addmin <= 1'b1;
				end
				else
					addmin <= 1'b0;
			end
			
			// switch out of clock set mode
			if (!KEY[0]) begin
				ClockSet <= 1'b0;
				ClockSetDummy <= 1;
			end
		end
		
		// switch to clock set mode
		if(sigcentisec && !KEY[1] && !ClockSet && DispMode == ModeClock) begin
			ClockSetCounter <= ClockSetCounter + 7'b1;
			if(ClockSetCounter == 7'd99) begin
				ClockSet <= 1'b1;
				// hack so that we don't increment a minute on entering clock set mode
				HourSet <= 1'b1;
				addmin <= 1'b0;
				addhour <= 1'b0;
				DontSetHours <= 1;
			end
		end
		else if (KEY[1] && !ClockSet)
			ClockSetCounter <= 7'b0;
			
		if(KEY[0])
			ClockSetDummy <= 0;
	end

	// Display mode - clock or stopwatch (initially clock)
	parameter ModeClock=1'b0;
	parameter ModeStWch=1'b1;
	reg DispMode=ModeClock;
 
	// Clock code
	reg [3:0] ClockHourHi=4'd0,ClockHourLo=4'd0,ClockMinsHi=4'd0,ClockMinsLo=4'd0;
	always @(posedge clk) begin
		ClockMinsLo <= clockmin;
		ClockMinsHi <= clockdecamin;
		ClockHourLo <= clockhour;
		ClockHourHi <= clockdecahour;
	end
	
	// Seconds on LEDG
	reg [5:0] SecondsCount=6'b0;
	always @(posedge clk) begin
		SecondsCount <= clocksec;
	end

	// Stopwatch code
	reg [3:0] StWchMinsHi=4'd0,StWchMinsLo=4'd0,StWchSecsHi=4'd0,StWchSecsLo=4'd0;
	reg [6:0] StWchCentisecs = 7'd0;
	reg [18:0] CountToCentiSecs = 19'd0;
	reg [2:0] StWchMode = ModeInit;
	parameter ModeInit = 0, Dummy1 = 1, ModeRunning = 2, Dummy2 = 3, ModeStopped = 4, Dummy3 = 6;
	reg reset = 1'b1;
	wire [3:0] swfullsec, swsec, swdecasec, swmin, swdecamin, swhour, swdecahour;
	reg SwitchModesDummy = 0;
	Timer stopwatch(CLOCK_50, 0, 0, swfullsec, swsec, swdecasec, swmin, swdecamin, swhour, swdecahour, reset);
	always @(posedge clk) begin
		if(DispMode == ModeStWch) begin
			case(StWchMode)
				ModeInit:begin
					reset <= 1'b1;
					StWchMinsHi <= 4'd0;
					StWchMinsLo <= 4'd0;
					StWchSecsHi <= 4'd0;
					StWchSecsLo <= 4'd0;
					StWchCentisecs <= 7'd0;
					if(!KEY[1]) begin 
						StWchMode <= Dummy1;
						reset <= 1'b0;
					end
				end
				Dummy1: begin
					if(KEY[1]) begin
						StWchMode <= ModeRunning;
					end
				end
				ModeRunning: begin
					StWchMinsHi <= swdecamin;
					StWchMinsLo <= swmin;
					StWchSecsHi <= swdecasec;
					StWchSecsLo <= swsec;
					
					if(CountToCentiSecs == 499999) begin
						StWchCentisecs <= StWchCentisecs + 1;
						CountToCentiSecs <= 0;
					end
					else
						CountToCentiSecs <= CountToCentiSecs + 1;
						
					if(!KEY[1])
						StWchMode <= Dummy2;
				end
				Dummy2: begin
					if(KEY[1]) begin
						StWchMode <= ModeStopped;
					end
				end
				ModeStopped:begin
					if(!KEY[1]) begin
						StWchMode <= Dummy3;
					end
				end
				Dummy3: begin
					if(KEY[1]) begin
						StWchMode <= ModeInit;
					end
				end
				default: begin
					reset <= 1'b1; 
					StWchMode <= ModeInit;
				end
			endcase
		end
		if(!KEY[0] && DispMode == ModeClock && !SwitchModesDummy && !ClockSet && !ClockSetDummy) begin
			DispMode <= ModeStWch;
			SwitchModesDummy <= 1;
		end
		else if(!KEY[0] && DispMode == ModeStWch && !SwitchModesDummy) begin
			DispMode <= ModeClock;
			SwitchModesDummy <= 1;
		end
		else if(KEY[0]) begin
			SwitchModesDummy <= 0;
		end
	end
	
	// Blinking control for clock set mode (flips on/off every half second)
	reg BlinkHi=1'b0;
	always @(posedge clk)
		if(sigsemisec)
			BlinkHi<=!BlinkHi;
	// Decide between displaying clock or stopwatch stuff
	wire [3:0] digit0,digit1,digit2,digit3;
	assign {digit3,digit2,digit1,digit0}=
		(DispMode==ModeStWch)?
			{StWchMinsHi,StWchMinsLo,StWchSecsHi,StWchSecsLo}:
		   {ClockHourHi,ClockHourLo,ClockMinsHi,ClockMinsLo};
	// Decode 4-bit values into 7-segment patterns
	wire [6:0] hex0tmp,hex1tmp,hex2tmp,hex3tmp;
	SevenSeg s0(.IN(digit0),.OUT(hex0tmp));
	SevenSeg s1(.IN(digit1),.OUT(hex1tmp));
	SevenSeg s2(.IN(digit2),.OUT(hex2tmp));
	SevenSeg s3(.IN(digit3),.OUT(hex3tmp));
	// This implements blinking in the clock-set mode
	assign {HEX3,HEX2,HEX1,HEX0}=
		((DispMode==ModeClock)&&ClockSet&&!BlinkHi)?
			28'hFFFFFFF:
			{hex3tmp,hex2tmp,hex1tmp,hex0tmp};
			
	assign LEDG[5:0] = (DispMode == ModeClock) ? SecondsCount : StWchCentisecs;
endmodule